﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufExtension.h"
#include "GnufItemEvents.h"
#include "GnufSubject.h"
#include "GnufQtObjectPtr.h"
#include "GnufItem.h"
#include "GnufButtonEx.h"
#include <QWidget>

/// \file GnufFilledRegionBoard.h
namespace gcmp
{
    class IFillPatternData;
    class IFillPattern;
}

namespace gnuf {

    class Toolbar;
    class ButtonEx;
    class Block;
    class QtToolbar;
    class AppearanceSetting;;
    class Item;
    /// \brief 填充样式下拉菜单
    /// \see IItemEventHandler
    class GNUF_EXTENSION_EXPORT GnufFilledPatternBoard final
        : public IItemEventHandler
    {
        CANNOT_COPY_OR_ASSIGN(GnufFilledPatternBoard)
    public:
        friend class QtFilledPatternBoard;
        friend class QtHatchPatternButtonControl;

        /// \brief 全局访问接口
        static GnufFilledPatternBoard* getInstance();
        /// \brief 根据填充样式生成Pixmap流化数据
        /// \param pData 填充样式的数据
        /// \param size 生成的pixmap的尺寸
        /// \param bUseRealScale 是否使用填充样式的缩放比例，默认为false，使用用户提供的缩放比例
        /// \return 返回填充样式的对应图案的流化数据
        /// \see IFillPatternData fillPatternScale
        static std::wstring generatePixmapByteArray(const gcmp::IFillPatternData* pData, const std::pair<int, int>& size, bool bUseRealScale = false);

        /// \brief 填充样式对应的缩放比例，在生成填充图案的时候需要使用
        static const std::unordered_map<std::wstring, float>& fillPatternScale() { return m_fillPatternScale; }
        /// \brief 设置填充样式对应的缩放比例
        static void setFillPatternScale(const std::unordered_map<std::wstring, float>& mapFillPatternScale);

        virtual ~GnufFilledPatternBoard();

        /// \brief 获取当前填充样式
        /// \details 当前的填充样式指的是，鼠标悬停的填充样式
        /// \return 当前填充样式名称
        inline std::wstring getCurrentPattern() const { return m_currPattern; }

        /// \brief 获取选中的填充样式
        /// \details 选中的填充样式指的是，鼠标点击的填充样式
        /// \return 选中的填充样式名称
        inline std::wstring getSelectedPatternName() const { return m_selectedPattern; }
        const gcmp::IFillPatternData* getSelectedPatternData() const;
        const gcmp::IFillPattern* getSelectedPattern() const;
        const gcmp::IFillPattern* getPatternByName(const std::wstring& name) const;

        void setCurrentPattern(const std::wstring& name);
        void setPatternDatas(const std::vector<const gcmp::IFillPattern*>& datas);
        const std::vector<const gcmp::IFillPattern*>& patternDatas() const { return m_fillPatternDatas; }

        inline void setMaximumColumn(int column) { m_maxColumn = column; }
        void setThumbnailIconSize(int width, int height);

        void setWidth(int width);
        void setHeight(int height);

        enum class EReferencePosition : std::uint8_t
        {
            eLeftBottom,
            eLeftTop
        };
        inline void setReference(Item* pItem) { m_reference = pItem; }
        inline Item* getReference() { return m_reference.Get(); }
        inline void setReferencePosition(EReferencePosition pos) { m_referencePos = pos; }
        inline EReferencePosition getReferencePosition() const { return m_referencePos; }

        /// \brief 初始化填充样式下拉菜单
        /// \details 在这一阶段，会创建面板上的控件，设置面板的样式
        void build();
        /// \brief 展示填充样式下拉菜单
        /// \details 在这一阶段，会show填充样式下拉菜单的Qt层实现
        void exec();
        QWidget* getQtImpl();
        void releaseQtImpl();

    protected:

        // Inherits from ItemEventHandler
        virtual void onHovered(Item* item, bool bHovered, void* qWidget) override; 
        virtual void onClicked(Item* item) override;

    private:
        GnufFilledPatternBoard(const std::string& customUniqueKey = "");

        void buildControls();
        void buildDatas();
        void setStyle();
        const Toolbar* getAllPatternToolbar() const;
        Toolbar* getAllPatternToolbar() { return m_allPatternToolbar.get(); }
        const Toolbar* getPreviewToolbar() const;
        Toolbar* getPreviewToolbar() { return m_previewToolbar.get(); }

        std::vector<const gcmp::IFillPattern*> m_fillPatternDatas;
        static std::unordered_map<std::wstring, float> m_fillPatternScale;
        std::wstring m_currPattern;
        std::wstring m_selectedPattern;
        std::pair<int, int> m_thumbnailIconSize;
        int m_maxColumn;
        int m_width;
        int m_height;
        EReferencePosition m_referencePos;

        gcmp::OwnerPtr<Toolbar> m_allPatternToolbar;
        gcmp::OwnerPtr<Toolbar> m_previewToolbar;
        ButtonEx*  m_previewButton;
        gcmp::WeakPtr<Block> m_patternBlock;
        gcmp::WeakPtr<Item> m_reference;
        gcmp::QtAutoPtr<QtFilledPatternBoard> m_qtImpl;
    };
}
